package com.hzw.saas.service.project.service.impl;

import java.util.Date;
import java.util.Objects;
import java.util.Optional;

import com.hzw.saas.api.template.IBusinessTemplateHandler;
import com.hzw.saas.api.template.bo.TemplateBO;
import com.hzw.saas.api.template.enums.TemplateTypeKeyEnum;
import com.hzw.saas.api.template.util.TemplateUtil;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.flow.pojo.bo.FlowProcessRecordBO;
import com.hzw.saas.common.flow.pojo.model.FlowInstance;
import com.hzw.saas.common.flow.pojo.model.FlowNode;
import com.hzw.saas.common.flow.service.IFlowInstanceService;
import com.hzw.saas.common.flow.service.IFlowNodeService;
import com.hzw.saas.common.flow.service.IFlowProcessRecordService;
import com.hzw.saas.common.util.constants.PatternConsts;
import com.hzw.saas.service.project.model.ProjectApply;
import com.hzw.saas.service.project.service.IProjectApplyService;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zzl
 * @since 09/08/2021
 */
@Service("projectApplyTemplateHandler")
@RequiredArgsConstructor
@Slf4j
public class ProjectApplyTemplateHandler implements IBusinessTemplateHandler {

    private final IProjectApplyService projectApplyService;
    private final IFlowInstanceService flowInstanceService;
    private final IFlowNodeService flowNodeService;
    private final IFlowProcessRecordService flowProcessRecordService;

    /**
     * @param template  模板
     * @param bizParams 项目申请ID
     * @return 正文
     */
    @Override
    public TemplateBO handle(TemplateBO template, String... bizParams) {
        if (ArrayUtil.isEmpty(bizParams) || Objects.isNull(template))
            return null;
        String projectApplyId = bizParams[0];
        ProjectApply apply = projectApplyService.getById(projectApplyId);
        AssertUtil.assertThrow("未找到项目申请信息", Objects.isNull(apply));
        FlowInstance instance = flowInstanceService.getById(apply.getFlowInstanceId());
        AssertUtil.assertThrow("未找到项目流程信息", Objects.isNull(instance));
        FlowNode flowNode = flowNodeService.getById(instance.getFlowNodeId());
        FlowProcessRecordBO record = flowProcessRecordService.getLatestPushOnRecord(apply.getFlowInstanceId());
        // 转换title
        String title = template.getTitle();
        title = this.replaceParams(apply, instance, flowNode, record, title);
        template.setTitle(title);
        // 转换content
        String content = template.getContent();
        content = this.replaceParams(apply, instance, flowNode, record, content);
        template.setContent(content);
        // 转换bizUrl
        String bizUrl = template.getBizUrl();
        bizUrl = this.replaceParams(apply, instance, flowNode, record, bizUrl);
        template.setBizUrl(bizUrl);
        // 转换bizTitle
        String bizTitle = template.getBizTitle();
        bizTitle = this.replaceParams(apply, instance, flowNode, record, bizTitle);
        template.setBizTitle(bizTitle);
        return template;
    }

    private String replaceParams(ProjectApply apply, FlowInstance instance, FlowNode flowNode, FlowProcessRecordBO record, String content) {
        if (StrUtil.isBlank(content)) {
            return content;
        }
        Optional<FlowNode> flowNodeOpt = Optional.ofNullable(flowNode);
        Optional<FlowProcessRecordBO> recordOpt = Optional.ofNullable(record);
        // projectApplyId
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_ID.getKey(), apply.getPid());
        // instanceId
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_FLOW_INSTANCE_ID.getKey(), instance.getPid());
        // username
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_USER_NAME.getKey(), apply.getUserName());
        // real name
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_REAL_NAME.getKey(), apply.getRealName());
        // phone
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_PHONE.getKey(), apply.getPhone());
        // email
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_EMAIL.getKey(), apply.getEmail());
        // project name
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_PROJECT_NAME.getKey(), apply.getProjectName());
        // flow node
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_FLOW_NODE.getKey(), flowNodeOpt.map(FlowNode::getFlowNodeName).orElse(" "));
        // suggestion
        content = content.replace(TemplateTypeKeyEnum.PROJECT_APPLY_LATEST_SUGGESTION.getKey(), recordOpt.map(FlowProcessRecordBO::getSuggestion).orElse(" "));
        // time
        content = this.replaceDate(content);
        return content;
    }

    private String replaceDate(String content) {
        String startStr = TemplateUtil.KEY_PREFIX.concat(TemplateTypeKeyEnum.CURRENT_DATE.getOriginKey()).concat("[");
        String endStr = "]".concat(TemplateUtil.KEY_SUFFIX);
        int startIndex = content.indexOf(startStr);
        int endIndex = content.indexOf(endStr, startIndex);
        if (Objects.equals(startIndex, -1) || Objects.equals(endIndex, -1)) {
            return this.replaceNormalDate(content);
        }
        Date now = new Date();
        String date = "";
        StringBuilder builder = new StringBuilder(content);
        try {
            String pattern = content.substring(startIndex + startStr.length(), endIndex);
            if (StrUtil.isBlank(pattern)) {
                return this.replaceNormalDate(content);
            }
            date = DateUtil.format(now, pattern);
        } catch (Exception e) {
            log.warn("模板时间变量解析失败, 使用通用时间格式...");
            date = DateUtil.format(now, PatternConsts.NORM_DATETIME_PATTERN);
        }
        return builder.replace(startIndex, endIndex + endStr.length(), date).toString();

    }

    private String replaceNormalDate(String content) {
        return content.replace(TemplateTypeKeyEnum.CURRENT_DATE.getKey(), DateUtil.format(new Date(), PatternConsts.NORM_DATETIME_PATTERN));
    }
}
